package com.lz.blog.service.impl;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.db.sql.Wrapper;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.lz.blog.dao.mapper.SysUserMapper;
import com.lz.blog.dao.pojo.SysUser;
import com.lz.blog.service.LoginService;
import com.lz.blog.service.SysUserService;
import com.lz.blog.utils.JWTUtils;
import com.lz.blog.vo.ErrorCode;
import com.lz.blog.vo.Result;
import com.lz.blog.vo.params.LoginParam;
import com.lz.blog.vo.params.RegisterParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author Liz
 * @date 2023/02/13 15:27
 **/
@Service
@Slf4j
public class LoginServiceImpl implements LoginService {
    @Resource
    private SysUserService sysUserService;

    @Resource
    private SysUserMapper sysUserMapper;

    @Resource
    private RedisTemplate<String, String> redisTemplate;

    private static final String slat = "123456Mszlu!@#$$";

    @Override
    public Result login(LoginParam loginParam) {
        /**
         * 1、检查参数是否合法
         * 2、根据用户名和密码去user查询，如果不存在就返回失败
         * 3、如果存在，使用jwt 生成token，放入到redis中，设置过期时间（登录认证的时候先认证token字符串是否合法，再去redis认证是否存在）
         */
        String account = loginParam.getAccount();
        String password = loginParam.getPassword();
        if (ObjectUtil.isEmpty(account) || ObjectUtil.isEmpty(password)) {
            return Result.fail(ErrorCode.PARAMS_ERROR.getCode(), ErrorCode.PARAMS_ERROR.getMsg());
        }
        //对密码进行MD5加密
        password = DigestUtil.md5Hex(password + slat);
        SysUser sysUser = sysUserService.findUser(account, password);
        if (ObjectUtil.isEmpty(sysUser)) {
            return Result.fail(ErrorCode.ACCOUNT_PWD_NOT_EXIST.getCode(), ErrorCode.ACCOUNT_PWD_NOT_EXIST.getMsg());
        }
        String token = JWTUtils.createToken(sysUser.getId());
        //存入redis并且设置过期时间
        redisTemplate.opsForValue().set("TOKEN_" + token, JSON.toJSONString(sysUser), 1, TimeUnit.DAYS);
        log.info("加密的token串为{}", token);
        return Result.success(token);
    }

    @Override
    public SysUser checkToken(String token) {
        if (ObjectUtil.isEmpty(token)) {
            return null;
        }
        Map<String, Object> stringObjectMap = JWTUtils.checkToken(token);
        if (ObjectUtil.isEmpty(stringObjectMap)) {
            return null;
        }
        String userJson = redisTemplate.opsForValue().get("TOKEN_" + token);
        if (ObjectUtil.isEmpty(userJson)) {
            return null;
        }
        return JSON.parseObject(userJson, SysUser.class);
    }

    @Override
    public Result logout(String token) {
        Boolean delete = redisTemplate.delete("TOKEN_" + token);
        log.info(String.valueOf(delete));
        return Result.success(null);
    }

    @Override
    @Transactional
    public Result register(RegisterParam registerParam) {
        /**
         * 注册的逻辑
         * 0、判断参数是否合法
         * 1、先拿出账户名判断数据库中是否有该数据，有的话返回
         * 2、没有的话，生成id，md5加密存储密码，nickname
         * 3、生成token
         * 4、存入redis
         * 5、注意加事务
         *
         */
        String account = registerParam.getAccount();
        String password = registerParam.getPassword();
        String nickname = registerParam.getNickname();

        if (ObjectUtil.isEmpty(account)
                || ObjectUtil.isEmpty(password)
                || ObjectUtil.isEmpty(nickname)) {
            return Result.fail(ErrorCode.PARAMS_ERROR.getCode(), ErrorCode.PARAMS_ERROR.getMsg());
        }
        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysUser::getAccount, account);
        List<SysUser> sysUserList = sysUserMapper.selectList(queryWrapper);
        if (ObjectUtil.isNotEmpty(sysUserList)) {
            return Result.fail(ErrorCode.ACCOUNT_EXIST.getCode(), ErrorCode.ACCOUNT_EXIST.getMsg());
        }
        //插入存储数据
        password = DigestUtil.md5Hex(password + slat);
        SysUser sysUser = new SysUser();
        sysUser.setNickname(nickname);
        sysUser.setAccount(account);
        sysUser.setPassword(password);
        sysUser.setCreateDate(System.currentTimeMillis());
        sysUser.setLastLogin(System.currentTimeMillis());
        sysUser.setAvatar("/static/img/logo.b3a48c0.png");
        sysUser.setAdmin(1);
        sysUser.setDeleted(0);
        //id自动生成，分布式雪花算法 mybatis-plus自带注解，
        sysUserMapper.insert(sysUser);
        //插入token到redis
        String token = JWTUtils.createToken(sysUser.getId());
        redisTemplate.opsForValue().set("TOKEN_" + token,JSON.toJSONString(sysUser),1,TimeUnit.DAYS);
        return Result.success(token);
    }
}
